package com.ysy.serviceImpl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ysy.config.ThreadPoolConfig;
import com.ysy.constant.RedisConstant;
import com.ysy.dto.UserDTO;
import com.ysy.entity.Fans;
import com.ysy.entity.req.FansListReqDTO;
import com.ysy.entity.rsp.FansUserRspVO;
import com.ysy.facade.UserFeignService;
import com.ysy.mapper.FansMapper;
import com.ysy.persimmons.common.response.PageResponse;
import com.ysy.persimmons.common.util.DateUtils;
import com.ysy.service.FansService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 用户粉丝表 服务实现类
 * </p>
 *
 * @author yangSy
 * @since 2025-04-26
 */
@Service
public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements FansService {


    @Resource
    private FansMapper fansMapper;

    @Resource
    private UserFeignService userFeignService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    @Resource(name = ThreadPoolConfig.RELATIONSHIP_EXECUTOR)
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;


    @Override
    public PageResponse<FansUserRspVO> fansList(FansListReqDTO fansListReq) {
        // 判断当前用户是设置了仅自己可见
        Long userId = fansListReq.getUserId();
        Integer pageNo = fansListReq.getPageNo();
        Integer pagSize = 10;
        String redisCacheKey = RedisConstant.buildUserFansKey(userId);
        Long total = redisTemplate.opsForZSet().zCard(redisCacheKey);

        List<FansUserRspVO> fansUserRspVOS = new ArrayList<>();

        if (total > 0) {

            long totalPage = PageResponse.getTotalPage(total, pagSize);

            if (pageNo>totalPage) {
                return PageResponse.success(null,pageNo,total);
            }
            long offset = PageResponse.getOffset(pageNo, pagSize);

            Set<Object> objects = redisTemplate.opsForZSet().reverseRangeByScore(redisCacheKey, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, offset, pagSize);
            if (objects != null && !objects.isEmpty()) {
                List<Long> fansIdList = objects.stream().map(v -> Long.parseLong(v.toString())).toList();
                extracted(fansIdList, fansUserRspVOS);
            }
        }else {
            total = fansMapper.selectCount(new QueryWrapper<Fans>().eq("user_id",userId));
           // long totalPage = PageResponse.getTotalPage(total, pagSize);
           // 1000 除10  限制只有1000存储
            if (pageNo>100) {
                return PageResponse.success(null,pageNo,total);
            }
            long offset = PageResponse.getOffset(pageNo, pagSize);

           List<Fans> fansList =  fansMapper.selectPageList(userId,offset,pagSize);

           if (!CollectionUtils.isEmpty(fansList)) {
               List<Long> fansIdList = fansList.stream().map(Fans::getFansUserId).toList();
               extracted(fansIdList, fansUserRspVOS);
               // 异步同步到redis
               threadPoolTaskExecutor.submit(()->{
                   redisCache(userId);
               });
           }

        }
        return PageResponse.success(fansUserRspVOS,pageNo,total);
    }

    private void redisCache(Long userId) {
        List<Fans> fansList = fansMapper.selectPageList(userId, 0, 1000);
        if (!CollectionUtils.isEmpty(fansList)) {
            DefaultRedisScript<Long> script = new DefaultRedisScript();
            script.setScriptSource(new ResourceScriptSource(new ClassPathResource("/lua/z_set_follow_batch_add_expire.lua")));
            script.setResultType(Long.class);
            int size = fansList.size()+ 1;
            Object[] args = new Object[size];
            int i=0;
            for (Fans fans : fansList) {
                args[i] = DateUtils.localDateTimeTimestamp(fans.getCreateTime());
                args[i+1] = fans.getFansUserId();
                i+=2;
            }
            args[size-1] = 60*60*5 + RandomUtil.randomInt(10);
            redisTemplate.execute(script,Collections.singletonList(userId.toString()),args);

        }


    }

    private void extracted(List<Long> fansIdList, List<FansUserRspVO> fansUserRspVOS) {
        List<UserDTO> fansUserList = userFeignService.findByIds(fansIdList);
        fansUserList.forEach(f -> {
            FansUserRspVO vo = new FansUserRspVO();
            vo.setUserId(f.getId());
            vo.setAvatar(f.getAvatar());
            vo.setName(f.getName());
            vo.setFansTotal(0L);
            vo.setNoteTotal(0L);
            fansUserRspVOS.add(vo);
        });
    }
}
